package gdconf

import (
	"database/sql/driver"
	"encoding/json"
	"fmt"
	"os"
	"server_cluster/common/logger"
	"server_cluster/common/protoc/pb"
)

type MonsterList []*Monster

func (m *MonsterList) Scan(value any) error {
	err := json.Unmarshal(value.([]byte), m)
	return err
}

func (m MonsterList) Value() (driver.Value, error) {
	data, err := json.Marshal(m)
	return string(data), err
}

type Monster struct {
	MonsterId int32
}

type NpcList []*Npc

func (n *NpcList) Scan(value any) error {
	err := json.Unmarshal(value.([]byte), n)
	return err
}

func (n NpcList) Value() (driver.Value, error) {
	data, err := json.Marshal(n)
	return string(data), err
}

type Npc struct {
	NpcId int32
}

type GadgetList []*Gadget

func (g *GadgetList) Scan(value any) error {
	err := json.Unmarshal(value.([]byte), g)
	return err
}

func (g GadgetList) Value() (driver.Value, error) {
	data, err := json.Marshal(g)
	return string(data), err
}

type Gadget struct {
	GadgetId     int32
	GadgetType   int32
	DefaultState int32
}

type FishPointList []*FishPoint

func (f *FishPointList) Scan(value any) error {
	err := json.Unmarshal(value.([]byte), f)
	return err
}

func (f FishPointList) Value() (driver.Value, error) {
	data, err := json.Marshal(f)
	return string(data), err
}

type FishPoint struct {
	FishPointId int32
}

type SceneData struct {
	SceneId       int32 `gorm:"primary_key;autoIncrement:false"`
	MonsterList   MonsterList
	NpcList       NpcList
	GadgetList    GadgetList
	FishPointList FishPointList
}

func (s *SceneData) Scan(value any) error {
	err := json.Unmarshal(value.([]byte), s)
	return err
}

func (s SceneData) Value() (driver.Value, error) {
	data, err := json.Marshal(s)
	return string(data), err
}

func (s *SceneData) TableName() string {
	return "config_scene_data"
}

func (g *GameDataConfig) saveSceneData() {
	sceneDataList := make([]*SceneData, 0)
	for _, sceneConfig := range readTable[SceneConfig](g.CsvPathPrefix + "Scene.csv") {
		filePath := g.JsonPathPrefix + "/" + sceneConfig.Name + ".json"
		fileData, err := os.ReadFile(filePath)
		if err != nil {
			logger.Error("找不到场景json配置:%v", filePath)
			continue
		}
		sceneJson := new(SceneJson)
		err = json.Unmarshal(fileData, sceneJson)
		if err != nil {
			logger.Error("解析场景json配置失败:%v", filePath)
			info := fmt.Sprintf("parse file error: %v", err)
			panic(info)
		}
		monsterList := make([]*Monster, 0)
		npcList := make([]*Npc, 0)
		gadgetList := make([]*Gadget, 0)
		fishPointList := make([]*FishPoint, 0)
		for _, sceneDataJson := range sceneJson.SceneDataJsonMap {
			switch sceneDataJson.Type {
			case SceneDataTypeMonster:
				monsterList = append(monsterList, &Monster{
					MonsterId: sceneDataJson.Id,
				})
			case SceneDataTypeNpc:
				npcList = append(npcList, &Npc{
					NpcId: sceneDataJson.Id,
				})
			case SceneDataTypeGadget:
				gadgetList = append(gadgetList, &Gadget{
					GadgetId:     sceneDataJson.Id,
					GadgetType:   sceneDataJson.GadgetType,
					DefaultState: sceneDataJson.DefaultState,
				})
			case SceneDataTypeFishPoint:
				fishPointList = append(fishPointList, &FishPoint{
					FishPointId: sceneDataJson.Id,
				})
			}
		}
		sceneDataList = append(sceneDataList, &SceneData{
			SceneId:       sceneConfig.Id,
			MonsterList:   monsterList,
			NpcList:       npcList,
			GadgetList:    gadgetList,
			FishPointList: fishPointList,
		})
	}
	saveTableToDb[SceneData](g.Db, sceneDataList)
}

func (g *GameDataConfig) loadSceneData() {
	g.GameDataMaps.SceneDataMap = make(map[int32]*SceneData)
	for _, sceneData := range loadTableFromDb[SceneData](g.Db) {
		g.GameDataMaps.SceneDataMap[sceneData.SceneId] = sceneData
	}
	logger.Info("SceneData Count: %v", len(g.GameDataMaps.SceneDataMap))
}

func GetSceneData(sceneId int32) *SceneData {
	value, exist := CONF.GameDataMaps.SceneDataMap[sceneId]
	if !exist {
		logger.Error("[ConfigNotFound] SceneData, sceneId: %v", sceneId)
		return nil
	}
	return value
}

func GetSceneDataMap() map[int32]*SceneData {
	return CONF.GameDataMaps.SceneDataMap
}

const (
	SceneDataTypeMonster   = 1
	SceneDataTypeNpc       = 2
	SceneDataTypeGadget    = 3
	SceneDataTypeFishPoint = 4
)

type SceneDataJson struct {
	Id           int32 `json:"ID"`
	Type         int32 `json:"Type"`
	GadgetType   int32 `json:"InteractFeatureType"`
	DefaultState int32 `json:"InteractInitState"`
}

type SceneJson struct {
	SceneDataJsonMap map[string]*SceneDataJson `json:"SceneDataDic"`
}

func PacketFishPointBySceneId(sceneId int32, entityList *[]*pb.SceneEntityInfo) {
	sceneData := GetSceneData(sceneId)
	if sceneData == nil {
		return
	}
	for _, fishPoint := range sceneData.FishPointList {
		*entityList = append(*entityList, &pb.SceneEntityInfo{Entity: &pb.SceneEntityInfo_FishPoint{FishPoint: &pb.SceneFishPointInfo{
			FishPointId: fishPoint.FishPointId,
			IsDestroy:   false,
		}}})
	}
}
